<template>
  <div class="setting">
    <!-- 侧边栏 -->
    <div class="sidebar">
      <a-menu
        mode="vertical"
        class="menu"
        v-model:selectedKeys="selectedKeys"
      >
        <a-menu-item key="avatar">
          <template #icon>
            <UserOutlined />
          </template>
          修改头像
        </a-menu-item>

        <a-menu-item key="profile">
          <template #icon>
            <UserOutlined />
          </template>
          个人信息
        </a-menu-item>

        <a-menu-item key="email">
          <template #icon>
            <MailOutlined />
          </template>
          修改邮箱
        </a-menu-item>
      </a-menu>
    </div>

    <div class="content">
      <div v-if="selectedKeys.includes('avatar')">
        <div class="avatar-section">
          <a-upload
            v-model:file-list="fileList"
            list-type="picture-card"
            :max-count="1"
            :show-upload-list="false"
            :before-upload="beforeUpload"
            @change="handleUpload"
          >
            <template v-if="userInfo?.avatar">
              <img
                :src="userInfo.avatar"
                alt="头像"
                class="avatar-image"
              />
            </template>
            <div v-else>
              <PlusOutlined />
            </div>
          </a-upload>
          <div class="avatar-tip">点击修改头像</div>
          <div class="avatar-upload-tip"> 图片格式仅支持：jpg 和 png，大小不超过 50MB</div>
        </div>
      </div>

      <div v-if="selectedKeys.includes('profile')">
        <a-form
          layout="vertical"
          class="form"
          :model="form"
          ref="formRef"
          :rules="rules"
        >
          <a-form-item
            label="昵称"
            name="nickname"
          >
            <a-input
              v-model:value="form.nickname"
              placeholder="请输入昵称"
              maxlength="30"
              show-count
            />
          </a-form-item>

          <a-form-item
            label="个性签名"
            name="signature"
          >
            <a-textarea
              v-model:value="form.signature"
              placeholder="请输入个性签名"
              :auto-size="{ minRows: 2, maxRows: 4 }"
              maxlength="50"
              show-count
            />
          </a-form-item>

          <a-form-item
            label="性别"
            name="sex"
          >
            <a-radio-group v-model:value="form.sex">
              <a-radio
                v-for="item in sexOptions"
                :value="item.value"
              >
                {{ item.label }}
              </a-radio>
            </a-radio-group>
          </a-form-item>
        </a-form>
      </div>

      <div v-if="selectedKeys.includes('email')">
        <a-form
          layout="vertical"
          class="form"
        >
          <a-form-item
            label="邮箱"
            required
          >
            <a-input
              v-model:value="userInfo.email"
              placeholder="请输入邮箱"
            >
              <template #prefix>
                <MailOutlined />
              </template>
            </a-input>
          </a-form-item>

          <a-form-item
            label="验证码"
            required
          >
            <a-input
              v-model:value="verificationCode"
              placeholder="请输入验证码"
            >
              <template #suffix>
                <a-button
                  :disabled="isSending"
                  @click="sendVerificationCode"
                >
                  {{ isSending ? `${countdown}秒后重试` : '获取验证码' }}
                </a-button>
              </template>
            </a-input>
          </a-form-item>
        </a-form>
      </div>

      <div
        class="setting-btn"
        v-if="!selectedKeys.includes('avatar')"
      >
        <a-button
          type="primary"
          class="save-btn"
          @click="saveChanges"
        >
          保存修改
        </a-button>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import type { PlatformUserProfileRespVO, PlatformUserProfileSaveReqVO } from '@/types/user'
import { MailOutlined, PlusOutlined, UserOutlined } from '@ant-design/icons-vue'
import { sexOptions } from '@/utils/options'
import { message, UploadChangeParam, UploadProps } from 'ant-design-vue'
import { modifyEmail, saveUserAvatar, saveUserProfile } from '@/api/user'
import { useUserStore } from '@/store/modules/user'
import { sha256 } from 'js-sha256'
import { checkFileExist } from '@/api/file'
import { Upload } from 'tus-js-client'
import { getAccessToken } from '@/utils/auth'
import { checkEmailCaptcha, sendEmailCaptcha } from '@/api/captcha'

const userStore = useUserStore()

/**
 * 用户个人信息
 */
const userInfo = defineModel<PlatformUserProfileRespVO>()

/**
 * 侧边菜单
 */
const selectedKeys = ref(['avatar'])

/**
 * 修改头像
 */
const uploadUrl = import.meta.env.VITE_UPLOAD_URL
const fileList = ref([])
const avatarUrl = ref('')
const isUploading = ref(false)

/**
 * 上传图片前校验
 */
const beforeUpload = (file: UploadProps['fileList'][number]) => {
  const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'

  if (!isJpgOrPng) {
    message.error('图片格式仅支持：jpg 和 png')
    return false
  }

  const isLt50M = file.size / 1024 / 1024 < 50
  if (!isLt50M) {
    message.error('图片大小不超过 50MB')
    return false
  }

  return isJpgOrPng && isLt50M
}

/**
 * 处理上传
 */
const handleUpload = async (info: UploadChangeParam) => {
  if (isUploading.value) {
    message.error('正在上传，请稍后')
    return
  }

  const file = info.file
  if (!file || !file.originFileObj) {
    return
  }

  isUploading.value = true
  try {
    const reader = new FileReader()
    reader.readAsArrayBuffer(file.originFileObj)
    reader.onload = async () => {
      if (reader.result) {
        const uint8View = new Uint8Array(reader.result as ArrayBuffer)
        let hash = sha256.create()
        hash.update(uint8View)
        const hex = hash.hex()
        const res = await checkFileExist(hex)
        if (res?.id && res?.path) {
          userInfo.value = {
            ...userInfo.value,
            avatar: res?.path
          }

          await saveUserAvatar(res?.id)
          await userStore.setUserInfo()
          message.success('上传成功')
        } else {
          if (uploadUrl) {
            const upload = new Upload(file.originFileObj, {
              endpoint: uploadUrl,
              metadata: {
                filename: file.name,
                uploadType: 'avatar',
                hash: hex
              },
              headers: {
                Authorization: `Bearer ${getAccessToken()}`
              },
              onError: error => {
                console.error('上传失败:', error)
                message.error('上传失败')
              },
              onProgress: (bytesUploaded, bytesTotal) => {
                const percentage = ((bytesUploaded / bytesTotal) * 100).toFixed(2)
                console.log(`上传进度: ${percentage}% (${bytesUploaded}/${bytesTotal})`)
              },
              onSuccess: async () => {
                const { id, path } = await checkFileExist(hex)
                if (id && path) {
                  userInfo.value = {
                    ...userInfo.value,
                    avatar: path
                  }

                  await saveUserAvatar(id)
                  await userStore.setUserInfo()
                  message.success('上传成功')
                } else {
                  message.error('上传失败，请重新上传')
                }
              }
            })

            await upload.start()
          }
        }
      }
    }
    reader.onerror = error => {
      message.error('上传失败: 计算文件哈希失败')
    }
  } catch (error) {
    console.error('上传失败:', error)
    message.error('上传失败')
  } finally {
    isUploading.value = false
    fileList.value = [] // 清空文件列表，避免重复触发 change 事件
  }
}

/**
 * 修改个人信息
 */
const form = reactive<PlatformUserProfileSaveReqVO>({
  nickname: '',
  sex: '',
  signature: ''
})

const formRef = ref()

const rules = {
  nickname: [
    { required: true, message: '请输入昵称', trigger: 'blur' },
    { min: 1, max: 30, message: '昵称长度在 1 到 30 个字符', trigger: 'blur' }
  ],
  sex: [{ required: true, message: '请选择性别', trigger: 'change' }],
  signature: [{ min: 0, max: 50, message: '签名长度在 0 到 50 个字符', trigger: 'blur' }]
}

/**
 * 保存个人信息
 */
const handleUserInfoSave = () => {
  if (!formRef.value) {
    return
  }

  formRef.value
    .validate()
    .then(async () => {
      await saveUserProfile(form)
      message.success('修改成功')

      userInfo.value = {
        ...userInfo.value,
        ...form
      }
      await userStore.setUserInfo()
    })
    .catch(error => {})
}

const verificationCode = ref('')
const isSending = ref(false)
const countdown = ref(60)
const uuid = ref('')

const sendVerificationCode = async () => {
  if (isSending.value) {
    return
  }

  if (!userInfo.value.email) {
    message.error('请输入邮箱')
    return
  }

  // 验证邮箱格式
  const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  if (!emailReg.test(userInfo.value.email)) {
    message.error('请输入有效的邮箱地址')
    return
  }

  // 模拟发送验证码的逻辑
  uuid.value = await sendEmailCaptcha(userInfo.value.email)
  if (!uuid.value) {
    message.error('发送验证码失败，请重新发送校验')
    return
  }

  isSending.value = true
  let timer = setInterval(() => {
    if (countdown.value > 0) {
      countdown.value--
    } else {
      clearInterval(timer)
      isSending.value = false
      countdown.value = 60
    }
  }, 1000)
}

/**
 * 保存按钮点击事件
 */
const saveChanges = async () => {
  if (selectedKeys.value.includes('profile')) {
    handleUserInfoSave()
  } else if (selectedKeys.value.includes('email')) {
    if (!uuid.value) {
      message.error('请先发送验证码')
      return
    }

    if (verificationCode.value === '') {
      message.error('请输入验证码')
      return
    }

    if (!userInfo.value.email) {
      message.error('请输入邮箱')
      return
    }

    // 验证邮箱格式
    const emailReg = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
    if (!emailReg.test(userInfo.value.email)) {
      message.error('请输入有效的邮箱地址')
      return
    }

    await checkEmailCaptcha(userInfo.value.email, verificationCode.value, uuid.value)
    try {
      await modifyEmail(userInfo.value.email)
      message.success('修改成功')
    } catch (error) {
    } finally {
      verificationCode.value = ''
      uuid.value = ''
    }
  }
}

watch(selectedKeys, () => {
  if (selectedKeys.value.includes('avatar')) {
    avatarUrl.value = userInfo.value.avatar
  } else if (selectedKeys.value.includes('profile')) {
    form.nickname = userInfo.value.nickname
    form.sex = userInfo.value.sex
    form.signature = userInfo.value.signature
  } else if (selectedKeys.value.includes('email')) {
    verificationCode.value = ''
    isSending.value = false
    countdown.value = 60
  }
})
</script>

<style scoped>
.setting {
  display: flex;
  gap: 40px;
  max-width: 1200px;
  margin: 0 auto;
  padding: 24px;
}

.sidebar {
  width: 260px;
  padding-right: 24px;
}

.avatar-section {
  text-align: center;
  margin-bottom: 32px;
}

.avatar-image {
  width: 120px;
  height: 120px;
  border-radius: 8px;
  object-fit: cover;
}

.avatar-tip {
  color: rgba(0, 0, 0, 0.45);
  margin-top: 20px;
  font-size: 12px;
}

.avatar-upload-tip {
  color: rgba(0, 0, 0, 0.45);
  margin-top: 8px;
  font-size: 12px;
  color: red;
}

.menu {
  border-right: none;
}

.content {
  flex: 1;
  padding: 0 24px;
}

.form {
  max-width: 600px;
}

.setting-btn {
  text-align: center;
}

.save-btn {
  margin: 24px auto;
  width: 200px;
}

:deep(.ant-upload-select-picture-card) {
  width: 120px;
  height: 120px;
  border-radius: 50%;
  margin: 0 auto;
}

:deep(.ant-upload-select-picture-card:hover) {
  border-color: #1890ff;
}
</style>
